#include "Snake.h"
#include <QWidget>
#include <stdio.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <qnumeric.h>
#include <qpainter.h>
#include <QKeyEvent>


Snake::Snake(QWidget* parent, int cellNum, int cellLen) : QWidget(parent)
{
	initWindow(cellNum, cellLen);
}
void Snake::init() {

	initGame();
	initCurrentPlayer();
	generateFood();
	startGameLoop();
}

void Snake::initWindow(int cellNum, int cellLen) {
	this->cellNumX = this->cellNumY = cellNum;
	this->cellLengthX = this->cellLengthY = cellLen;
	this->setFixedWidth(cellNumY * cellLengthY);
	this->setFixedHeight(cellNumY * cellLengthY);
}

void Snake::initGame()
{
	board = new Role * [cellNumX];
	for (int i = 0;i < cellNumX;i++) {
		board[i] = new Role[cellNumY];
	}
	for (int i = 1; i < cellNumX - 1;i++) {
		for (int j = 1;j < cellNumY - 1;j++) {
			board[i][j] = NOTHING;
		}
	}
	for (int i = 0; i < cellNumX;i++) {
		board[i][0] = WALL;
		board[i][cellNumY - 1] = WALL;
		board[0][i] = WALL;
		board[cellNumX - 1][i] = WALL;
	}
}

void Snake::initCurrentPlayer() {
	direct = newDirect = RIGHT;
	snake.clear();
	snake.enqueue(QPoint(1, cellNumY / 2));
	snake.enqueue(QPoint(2, cellNumY / 2));
	snake.enqueue(QPoint(3, cellNumY / 2));
	board[1][cellNumY / 2] = SNAKEBODY;
	board[2][cellNumY / 2] = SNAKEBODY;
	board[3][cellNumY / 2] = SNAKEHEAD;
}

void Snake::generateFood()
{
	qRound((float)QTime::currentTime().msec());
	do {
		int x = 1 + rand() % (cellNumX - 1);
		int y = 1 + rand() % (cellNumY - 1);
		if (board[x][y] == NOTHING) {
			board[x][y] = FOOD;
			break;
		}

	} while (true);
}

void Snake::startGameLoop() {
	timer = new QTimer(this);
	connect(timer, &QTimer::timeout, this, &Snake::loopGame);
	timer->start(1000 / 2);
}
void Snake::loopGame() {
	doKeyEvent();
	doGameLogic();
	renderGameFrame();
}
void Snake::renderGameFrame() {
	update();
}

void Snake::updateCurrentPlayer() {
	QPoint delPoint;
	QPoint snakeHead = snake.last();
	int newCellX = snakeHead.x();
	int newCellY = snakeHead.y();

	switch (direct) {
	case UP:
		newCellY -= 1;
		break;
	case DOWN:
		newCellY += 1;
		break;
	case LEFT:
		newCellX -= 1;
		break;
	case RIGHT:
		newCellX += 1;
		break;
	}

	switch (board[newCellX][newCellY]) {
	case SNAKEBODY:
		overGame();
		break;
	case NOTHING:
		snake.enqueue(QPoint(newCellX, newCellY));
		delPoint = snake.dequeue();
		board[snakeHead.x()][snakeHead.y()] = SNAKEBODY;
		board[newCellX][newCellY] = SNAKEHEAD;
		board[delPoint.x()][delPoint.y()] = NOTHING;
		break;
	case FOOD:
		snake.enqueue(QPoint(newCellX, newCellY));
		board[snakeHead.x()][snakeHead.y()] = SNAKEBODY;
		board[newCellX][newCellY] = SNAKEHEAD;
		generateFood();
		break;

	}
}

void Snake::doGameLogic() {
	updateCurrentPlayer();
}
void Snake::doKeyEvent() {
	switch (newDirect) {
	case UP:
		if (direct != DOWN) {
			direct = UP;
		}
		break;
	case DOWN:
		if (direct != UP) {
			direct = DOWN;
		}
		break;
	case LEFT:
		if (direct != RIGHT) {
			direct = LEFT;
		}
		break;
	case RIGHT:
		if (direct != LEFT) {
			direct = RIGHT;
		}
		break;
	}
}

void Snake::overGame() {

}

void Snake::paintEvent(QPaintEvent* event)
{
	QPainter painter(this);

	QBrush brush(Qt::SolidPattern);

	for (int i = 0; i < cellNumX;i++) {
		for (int j = 0;j < cellNumY;j++) {
			brush.setColor(QColor(255, 255, 200));
			switch (board[i][j]) {
			case NOTHING:
				brush.setColor(QColor(255, 255, 200));
				break;
			case WALL:
				brush.setColor(Qt::black);
				break;
			case FOOD:
				brush.setColor(Qt::red);
				break;
			case SNAKEBODY:
				brush.setColor(Qt::gray);
				break;
			case SNAKEHEAD:
				brush.setColor(Qt::blue);
				break;
			}
			painter.setBrush(brush);
			painter.drawRect(i * cellLengthX, j * cellLengthY, cellLengthX, cellLengthY);
		}
	}
}
void Snake::keyEvent(QKeyEvent* event) {
	switch (event->key()) {
	case Qt::Key_Up:
		newDirect = UP;
		break;
	case Qt::Key_Down:
		newDirect = DOWN;
		break;
	case Qt::Key_Left:
		newDirect = LEFT;
		break;
	case Qt::Key_Right:
		newDirect = RIGHT;
		break;
	}
}

Snake::~Snake()
{
}